package com.ttloner2.dao;

import java.io.InputStream;
import java.lang.reflect.Field;
import java.sql.*;
import java.util.ArrayList;
import java.util.Properties;

/**
 * @author TTLoner
 * @date 2021/6/24 19:51
 * @description
 */
//工具类一般都为抽象类
public abstract class BaseDAO {
    public static Connection getConnection()  {
        Connection conn=null;
        try {
            //1.读取配置
            InputStream resourceAsStream = ClassLoader.getSystemClassLoader().getResourceAsStream("jdbc.properties");
            Properties properties = new Properties();
            properties.load(resourceAsStream);
            String user = properties.getProperty("user");
            String password = properties.getProperty("password");
            String url = properties.getProperty("url");
            String driverClass = properties.getProperty("driverClass");
            //2.加载驱动
            Class.forName(driverClass);
            //3.获取连接
            conn = DriverManager.getConnection(url, user, password);
        } finally {
            //4.返回连接
            return conn;
        }
    }

    public static void closeConnection(Connection conn, PreparedStatement ps, ResultSet rs){
        try {
            if(conn!=null) conn.close();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        try {
            if(ps!=null) ps.close();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        try {
            if(rs!=null) rs.close();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
    }

    public static int update(Connection conn,String sql,Object...args){
        PreparedStatement ps = null;
        int excuteNum=0;
        try {
            //2.预编译sql语句，返回ps
            ps = conn.prepareStatement(sql);
            //3.填充占位符
            for(int i=0;i<args.length;i++){
                ps.setObject(i+1,args[i]);
            }
            //4.执行,并返回处理的行数
            excuteNum = ps.executeUpdate();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally{
            //5.关闭资源
            try {
                ps.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
        return excuteNum;
    }

    public static <T> ArrayList<T> getInstance(Connection conn, Class<T> clazz, String sql, Object...args) throws InstantiationException {
        ArrayList<T> result = new ArrayList<>();
        //连接数据库
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
            //预编译
            ps = conn.prepareStatement(sql);
            for(int i=0;i<args.length;i++){
                ps.setObject(i+1,args[i]);
            }
            //获取结果
            rs = ps.executeQuery();
            //获取元数据
            ResultSetMetaData metaData = rs.getMetaData();
            int count = metaData.getColumnCount();
            while(rs.next()){
//                ExamStudent ES = new ExamStudent();
                T t = clazz.newInstance();
                for(int i=0;i<count;i++){
                    //获取列的列名，不推荐使用
//                    String CName = metaData.getColumnName(i+1);
                    String CName = metaData.getColumnLabel(i+1);
                    //获取列的别名：getColumnLabel
                    //通过反射获取
                    Field field = clazz.getDeclaredField(CName);
                    field.setAccessible(true);
                    Object o = rs.getObject(i + 1);
                    field.set(t, o);

                }
                result.add(t);
            }

        } catch (SQLException throwables) {
            throwables.printStackTrace();
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }finally {
            //关闭流
            try {
                if(rs!=null) rs.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
            try {
                if(ps!=null) ps.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
        return result;
    }

    //添加新的功能，用于查询特殊值，例如count(*)
    public static <E> E getSingleValue(Connection conn, String sql, Object...args) {
        E result=null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
            ps = conn.prepareStatement(sql);
            for(int i=0;i<args.length;i++){
                ps.setObject(i+1,args[i]);
            }
            rs = ps.executeQuery();
            if(rs.next()) {
                result = (E) rs.getObject(1);
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        } finally {
            closeConnection(null,ps,rs);
            return result;
        }
    }
}
